
from mcp.server.fastmcp import FastMCP
import asyncio
import math
import numpy as np
import scipy.optimize as opt
import scipy.interpolate as interp
from scipy.interpolate import CubicSpline
import scipy.integrate as integrate
from scipy.stats import jarque_bera, shapiro
from sklearn.linear_model import Ridge, Lasso
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.metrics import r2_score, mean_squared_error
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import seaborn as sns
import plotly.graph_objects as go
import plotly.express as px
import warnings
import base64
import io
from typing import Union, List, Dict, Any, Tuple, Optional
import sympy as sp
import re
import os
import platform
import datetime

warnings.filterwarnings('ignore')

# 配置中文字体支持
def setup_chinese_fonts():
    """设置中文字体支持"""
    try:
        # 根据操作系统选择合适的中文字体
        system = platform.system()
        if system == "Windows":
            chinese_fonts = ['SimHei', 'Microsoft YaHei', 'SimSun', 'KaiTi']
        elif system == "Darwin":  # macOS
            chinese_fonts = ['PingFang SC', 'Heiti SC', 'STHeiti', 'Arial Unicode MS']
        else:  # Linux
            chinese_fonts = ['WenQuanYi Micro Hei', 'DejaVu Sans', 'Liberation Sans']
        
        # 获取系统可用字体
        available_fonts = [f.name for f in fm.fontManager.ttflist]
        
        # 选择第一个可用的中文字体
        selected_font = None
        for font in chinese_fonts:
            if font in available_fonts:
                selected_font = font
                break
        
        if selected_font:
            plt.rcParams['font.sans-serif'] = [selected_font]
            print(f"已设置中文字体: {selected_font}")
        else:
            # 如果没有找到中文字体，使用默认字体并警告
            plt.rcParams['font.sans-serif'] = ['DejaVu Sans']
            print("警告: 未找到中文字体，使用默认字体")
        
        # 设置其他字体参数
        plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
        plt.rcParams['font.family'] = 'sans-serif'
        plt.rcParams['font.size'] = 12
        
        return True
    except Exception as e:
        print(f"字体设置失败: {e}")
        plt.rcParams['font.family'] = 'DejaVu Sans'
        return False

# 初始化中文字体
setup_chinese_fonts()

def ensure_utf8_encoding(text):
    """确保文本使用UTF-8编码"""
    if isinstance(text, str):
        return text
    elif isinstance(text, bytes):
        try:
            return text.decode('utf-8')
        except UnicodeDecodeError:
            try:
                return text.decode('gbk')
            except UnicodeDecodeError:
                return text.decode('utf-8', errors='ignore')
    else:
        return str(text)

def safe_file_path(path):
    """确保文件路径能正确处理中文字符"""
    try:
        # 确保路径是字符串格式
        path = ensure_utf8_encoding(path)
        # 规范化路径
        path = os.path.normpath(path)
        # 确保目录存在
        directory = os.path.dirname(path)
        if directory and not os.path.exists(directory):
            os.makedirs(directory, exist_ok=True)
        return path
    except Exception as e:
        print(f"路径处理错误: {e}")
        return path

def format_friendly_expression(expr_str: str) -> str:
    """
    将复杂的数学表达式转换为更友好的格式
    """
    try:
        # 移除多余的空格
        expr_str = re.sub(r'\s+', ' ', str(expr_str).strip())
        
        # 替换常见的数学符号
        replacements = {
            '**': '^',
            '*': '·',
            'sqrt': '√',
            'exp': 'e^',
            'log': 'ln',
            'pi': 'π',
            'E': 'e'
        }
        
        for old, new in replacements.items():
            expr_str = expr_str.replace(old, new)
        
        # 简化系数显示
        expr_str = re.sub(r'(\d+\.\d{6,})', lambda m: f"{float(m.group(1)):.4f}", expr_str)
        
        return expr_str
    except Exception:
        return str(expr_str)

# 创建MCP服务器实例
mcp = FastMCP("mcp-basic-curvefitting")
@mcp.tool()
def polynomial_interpolation(x_points: List[float], y_points: List[float], method: str = "lagrange", derivatives: Optional[List[float]] = None) -> Union[Dict[str, Any], str]:
    """
    多项式插值算法
    
    Args:
        x_points: x坐标点
        y_points: y坐标点
        method: 插值方法 (lagrange, newton, cubic_spline, rbf, hermite)
        derivatives: 埃尔米特插值所需的导数值（仅在method="hermite"时使用）
    
    Returns:
        插值结果和系数
    """
    try:
        x_points = np.array(x_points)
        y_points = np.array(y_points)
        
        if len(x_points) != len(y_points):
            return "错误：x和y坐标点数量不匹配"
        
        if method == "lagrange":
            # 拉格朗日插值
            def lagrange_poly(x):
                result = 0
                n = len(x_points)
                for i in range(n):
                    term = y_points[i]
                    for j in range(n):
                        if i != j:
                            term *= (x - x_points[j]) / (x_points[i] - x_points[j])
                    result += term
                return result
            
            # 生成符号表达式和LaTeX公式
            try:
                x_sym = sp.Symbol('x')
                lagrange_expr = 0
                n = len(x_points)
                
                for i in range(n):
                    term = y_points[i]
                    for j in range(n):
                        if i != j:
                            term *= (x_sym - x_points[j]) / (x_points[i] - x_points[j])
                    lagrange_expr += term
                
                # 展开并简化多项式
                lagrange_expanded = sp.expand(lagrange_expr)
                latex_formula = sp.latex(lagrange_expanded)
            except Exception as latex_error:
                latex_formula = f"LaTeX生成错误: {str(latex_error)}"
                lagrange_expanded = "符号表达式生成失败"
            
            # 生成测试点
            x_test = np.linspace(min(x_points), max(x_points), 100)
            y_test = [lagrange_poly(x) for x in x_test]
            
            # 确保LaTeX公式是字符串类型
            latex_str = str(latex_formula) if latex_formula else "LaTeX公式生成失败"
            symbolic_str = str(lagrange_expanded) if lagrange_expanded else "符号表达式生成失败"
            
            # 生成友好的数学公式格式
            def format_display_formula(latex_str, symbolic_str):
                """生成适合直接显示的数学公式格式"""
                if "LaTeX公式生成失败" in latex_str or "错误" in latex_str:
                    # 如果LaTeX生成失败，使用符号表达式
                    if "符号表达式生成失败" not in symbolic_str:
                        return f"f(x) = {symbolic_str}"
                    else:
                        return "公式生成失败"
                
                # 返回LaTeX格式的公式，用于直接显示
                return f"$$f(x) = {latex_str}$$"
            
            display_formula = format_display_formula(latex_str, symbolic_str)
            
            # 生成友好格式的表达式
            friendly_formula = format_friendly_expression(symbolic_str)
            
            result = {
                "method": "拉格朗日插值",
                "x_interpolated": x_test.tolist(),
                "y_interpolated": y_test,
                "original_points": {"x": x_points.tolist(), "y": y_points.tolist()},
                "latex_formula": latex_str,
                "symbolic_expression": symbolic_str,
                "display_formula": display_formula,  # 适合直接显示的数学公式
                "friendly_formula": friendly_formula,
                "formula_info": {
                    "latex_length": len(latex_str),
                    "has_latex": bool(latex_str and latex_str != "LaTeX公式生成失败")
                }
            }
            print(f"DEBUG: 拉格朗日插值 - LaTeX公式: {latex_str}")
            print(f"DEBUG: 拉格朗日插值 - 原始符号表达式: {symbolic_str}")
            print(f"DEBUG: 拉格朗日插值 - 显示公式: {display_formula}")
            print(f"DEBUG: 拉格朗日插值 - 友好格式变量: {friendly_formula}")
            print(f"DEBUG: 拉格朗日插值 - 结果字典键: {list(result.keys())}")
            print(f"DEBUG: 拉格朗日插值 - symbolic_expression字段值: {result['symbolic_expression']}")
            return result
        
        elif method == "newton":
            # 牛顿插值（差分法）
            def newton_divided_differences(x_vals, y_vals):
                n = len(x_vals)
                # 创建差分表
                diff_table = np.zeros((n, n))
                diff_table[:, 0] = y_vals
                
                for j in range(1, n):
                    for i in range(n - j):
                        diff_table[i, j] = (diff_table[i + 1, j - 1] - diff_table[i, j - 1]) / (x_vals[i + j] - x_vals[i])
                
                return diff_table[0, :]
            
            def newton_poly(x, x_vals, coeffs):
                result = coeffs[0]
                for i in range(1, len(coeffs)):
                    term = coeffs[i]
                    for j in range(i):
                        term *= (x - x_vals[j])
                    result += term
                return result
            
            coeffs = newton_divided_differences(x_points, y_points)
            
            # 生成符号表达式和LaTeX公式
            try:
                x_sym = sp.Symbol('x')
                newton_expr = coeffs[0]
                
                for i in range(1, len(coeffs)):
                    term = coeffs[i]
                    for j in range(i):
                        term *= (x_sym - x_points[j])
                    newton_expr += term
                
                # 展开并简化多项式
                newton_expanded = sp.expand(newton_expr)
                latex_formula = sp.latex(newton_expanded)
            except Exception as latex_error:
                latex_formula = f"LaTeX生成错误: {str(latex_error)}"
                newton_expanded = "符号表达式生成失败"
            
            x_test = np.linspace(min(x_points), max(x_points), 100)
            y_test = [newton_poly(x, x_points, coeffs) for x in x_test]
            
            # 确保LaTeX公式是字符串类型
            latex_str = str(latex_formula) if latex_formula else "LaTeX公式生成失败"
            symbolic_str = str(newton_expanded) if newton_expanded else "符号表达式生成失败"
            
            # 生成友好的数学公式格式
            def format_display_formula(latex_str, symbolic_str):
                """生成适合直接显示的数学公式格式"""
                if "LaTeX公式生成失败" in latex_str or "错误" in latex_str:
                    # 如果LaTeX生成失败，使用符号表达式
                    if "符号表达式生成失败" not in symbolic_str:
                        return f"f(x) = {symbolic_str}"
                    else:
                        return "公式生成失败"
                
                # 返回LaTeX格式的公式，用于直接显示
                return f"$$f(x) = {latex_str}$$"
            
            display_formula = format_display_formula(latex_str, symbolic_str)
            
            result = {
                "method": "牛顿插值",
                "coefficients": coeffs.tolist(),
                "x_interpolated": x_test.tolist(),
                "y_interpolated": y_test,
                "original_points": {"x": x_points.tolist(), "y": y_points.tolist()},
                "latex_formula": latex_str,
                "symbolic_expression": symbolic_str,
                "display_formula": display_formula,  # 适合直接显示的数学公式
                "formula_info": {
                    "latex_length": len(latex_str),
                    "has_latex": bool(latex_str and latex_str != "LaTeX公式生成失败")
                }
            }
            print(f"DEBUG: 牛顿插值 - LaTeX公式: {latex_str}")
            print(f"DEBUG: 牛顿插值 - 符号表达式: {symbolic_str}")
            print(f"DEBUG: 牛顿插值 - 结果字典键: {list(result.keys())}")
            return result
        
        elif method == "cubic_spline":
            try:
                # 转换为numpy数组并检查维度
                x_points = np.array(x_points, dtype=np.float64)
                y_points = np.array(y_points, dtype=np.float64)
                
                print(f"原始数据维度检查:")
                print(f"x_points长度: {len(x_points)}, 内容: {x_points}")
                print(f"y_points长度: {len(y_points)}, 内容: {y_points}")
                
                # 检查输入数据维度
                if len(x_points) != len(y_points):
                    raise ValueError(f"x和y坐标点数量不匹配: x有{len(x_points)}个点，y有{len(y_points)}个点")
                
                # 检查数据有效性
                if len(x_points) < 2:
                    raise ValueError("至少需要2个数据点进行三次样条插值")
                
                # 确保x坐标是严格递增的
                if not np.all(np.diff(x_points) >= 0):
                    # 如果x不是严格递增，进行排序
                    sorted_indices = np.argsort(x_points)
                    x_points = x_points[sorted_indices]
                    y_points = y_points[sorted_indices]
                    print(f"数据已按x坐标排序")
                
                # 创建三次样条插值对象
                cs = CubicSpline(x_points, y_points)
                
                # 生成插值点 - 确保数量一致且为整数
                num_points = 100  # 固定插值点数量
                x_test = np.linspace(x_points.min(), x_points.max(), num_points)
                
                # 计算插值结果
                y_test = cs(x_test)

                
                print(f"插值后数据维度检查:")
                print(f"x_test长度: {len(x_test)}, 类型: {type(x_test)}, dtype: {x_test.dtype}")
                print(f"y_test长度: {len(y_test)}, 类型: {type(y_test)}, dtype: {y_test.dtype}")

                
                # 验证最终维度
                if len(x_test) != len(y_test):
                    raise ValueError(f"维度修正失败: x_test长度={len(x_test)}, y_test长度={len(y_test)}")
                
                print(f"最终维度修正后: x_test长度={len(x_test)}, y_test长度={len(y_test)}")
                
                # 转换为列表，确保JSON序列化兼容性
                x_interpolated_list = [float(x) for x in x_test]
                y_interpolated_list = [float(y) for y in y_test]
                
                # 返回结果
                result = {
                    "method": "三次样条插值",
                    "x_interpolated": x_interpolated_list,
                    "y_interpolated": y_interpolated_list,
                    "original_points": {
                        "x": [float(x) for x in x_points],
                        "y": [float(y) for y in y_points]
                    },
                    "interpolation_info": {
                        "original_points_count": len(x_points),
                        "interpolated_points_count": len(x_interpolated_list),
                        "x_range": [float(x_points.min()), float(x_points.max())],
                        "y_range": [float(min(y_interpolated_list)), float(max(y_interpolated_list))],
                        "dimension_check": {
                            "x_length": len(x_interpolated_list),
                            "y_length": len(y_interpolated_list),
                            "is_consistent": len(x_interpolated_list) == len(y_interpolated_list)
                        }
                    }
                }
                
                print(f"最终结果维度验证:")
                print(f"x_interpolated长度: {len(result['x_interpolated'])}")
                print(f"y_interpolated长度: {len(result['y_interpolated'])}")
                print(f"维度一致性: {result['interpolation_info']['dimension_check']['is_consistent']}")
                
                return result
                
            except Exception as e:
                print(f"三次样条插值错误: {str(e)}")
                return {"error": f"三次样条插值失败: {str(e)}"}


        
        elif method == "rbf":
            # 径向基函数插值
            from scipy.interpolate import Rbf
            rbf = Rbf(x_points, y_points, function='multiquadric')
            
            x_test = np.linspace(min(x_points), max(x_points), 100)
            y_test = rbf(x_test)
            
            return {
                "method": "径向基函数插值",
                "x_interpolated": x_test.tolist(),
                "y_interpolated": y_test.tolist(),
                "original_points": {"x": x_points.tolist(), "y": y_points.tolist()}
            }
        
        elif method == "hermite":
            # 埃尔米特插值
            if derivatives is None:
                return "错误：埃尔米特插值需要提供导数值"
            
            if len(derivatives) != len(x_points):
                return "错误：导数值数量必须与数据点数量相同"
            
            # 使用scipy的CubicHermiteSpline进行埃尔米特插值
            from scipy.interpolate import CubicHermiteSpline
            derivatives = np.array(derivatives)
            hermite_interp = CubicHermiteSpline(x_points, y_points, derivatives)
            
            x_test = np.linspace(min(x_points), max(x_points), 100)
            y_test = hermite_interp(x_test)
            
            return {
                "method": "埃尔米特插值",
                "x_interpolated": x_test.tolist(),
                "y_interpolated": y_test.tolist(),
                "original_points": {"x": x_points.tolist(), "y": y_points.tolist()},
                "derivatives": derivatives.tolist()
            }
        
        return "错误：不支持的插值方法"
        
    except Exception as e:
        return f"错误：插值计算失败 - {str(e)}"



@mcp.tool()
def curve_fitting(x_data: List[float], y_data: List[float], degree: int = 2, method: str = "polynomial", alpha: float = 1.0) -> Union[Dict[str, Any], str]:
    """
    曲线拟合算法
    
    Args:
        x_data: x数据点
        y_data: y数据点
        degree: 多项式次数
        method: 拟合方法 (polynomial, exponential, logarithmic, ridge, lasso)
        alpha: 正则化参数（用于ridge和lasso）
    
    Returns:
        拟合结果和参数，包含R²和RMSE评估
    """
    try:
        x_data = np.array(x_data)
        y_data = np.array(y_data)
        
        if len(x_data) != len(y_data):
            return "错误：x和y数据点数量不匹配"
        
        if method == "polynomial":
            # 多项式拟合
            coeffs = np.polyfit(x_data, y_data, degree)
            poly = np.poly1d(coeffs)
            
            # 计算拟合优度
            y_pred = poly(x_data)
            r_squared = 1 - np.sum((y_data - y_pred) ** 2) / np.sum((y_data - np.mean(y_data)) ** 2)
            rmse = np.sqrt(np.mean((y_data - y_pred) ** 2))
            
            # 生成拟合曲线
            x_fit = np.linspace(min(x_data), max(x_data), 100)
            y_fit = poly(x_fit)
            
            return {
                "method": f"{degree}次多项式拟合",
                "coefficients": coeffs.tolist(),
                "r_squared": float(r_squared),
                "rmse": float(rmse),
                "x_fitted": x_fit.tolist(),
                "y_fitted": y_fit.tolist(),
                "original_data": {"x": x_data.tolist(), "y": y_data.tolist()}
            }
        
        elif method == "exponential":
            # 指数拟合 y = a * exp(b * x)
            from scipy.optimize import curve_fit
            
            def exp_func(x, a, b):
                return a * np.exp(b * x)
            
            popt, pcov = curve_fit(exp_func, x_data, y_data)
            
            # 计算拟合优度
            y_pred = exp_func(x_data, *popt)
            r_squared = 1 - np.sum((y_data - y_pred) ** 2) / np.sum((y_data - np.mean(y_data)) ** 2)
            rmse = np.sqrt(np.mean((y_data - y_pred) ** 2))
            
            # 生成拟合曲线
            x_fit = np.linspace(min(x_data), max(x_data), 100)
            y_fit = exp_func(x_fit, *popt)
            
            return {
                "method": "指数拟合",
                "parameters": {"a": float(popt[0]), "b": float(popt[1])},
                "r_squared": float(r_squared),
                "rmse": float(rmse),
                "x_fitted": x_fit.tolist(),
                "y_fitted": y_fit.tolist(),
                "original_data": {"x": x_data.tolist(), "y": y_data.tolist()}
            }
        
        elif method == "logarithmic":
            # 对数拟合 y = a * ln(x) + b
            from scipy.optimize import curve_fit
            
            def log_func(x, a, b):
                return a * np.log(x) + b
            
            # 确保x > 0
            if np.any(x_data <= 0):
                return "错误：对数拟合要求所有x值大于0"
            
            popt, pcov = curve_fit(log_func, x_data, y_data)
            
            # 计算拟合优度
            y_pred = log_func(x_data, *popt)
            r_squared = 1 - np.sum((y_data - y_pred) ** 2) / np.sum((y_data - np.mean(y_data)) ** 2)
            rmse = np.sqrt(np.mean((y_data - y_pred) ** 2))
            
            # 生成拟合曲线
            x_fit = np.linspace(min(x_data), max(x_data), 100)
            y_fit = log_func(x_fit, *popt)
            
            return {
                "method": "对数拟合",
                "parameters": {"a": float(popt[0]), "b": float(popt[1])},
                "r_squared": float(r_squared),
                "rmse": float(rmse),
                "x_fitted": x_fit.tolist(),
                "y_fitted": y_fit.tolist(),
                "original_data": {"x": x_data.tolist(), "y": y_data.tolist()}
            }
        
        elif method == "ridge":
            # Ridge回归（岭回归）
            # 生成多项式特征
            poly_features = PolynomialFeatures(degree=degree)
            X_poly = poly_features.fit_transform(x_data.reshape(-1, 1))
            
            # Ridge回归拟合
            ridge = Ridge(alpha=alpha)
            ridge.fit(X_poly, y_data)
            
            # 预测和评估
            y_pred = ridge.predict(X_poly)
            r_squared = ridge.score(X_poly, y_data)
            rmse = np.sqrt(mean_squared_error(y_data, y_pred))
            mae = np.mean(np.abs(y_data - y_pred))  # 平均绝对误差
            
            # 生成拟合曲线
            x_fit = np.linspace(min(x_data), max(x_data), 100)
            X_fit_poly = poly_features.transform(x_fit.reshape(-1, 1))
            y_fit = ridge.predict(X_fit_poly)
            
            return {
                "method": f"Ridge回归（{degree}次多项式）",
                "coefficients": ridge.coef_.tolist(),
                "intercept": float(ridge.intercept_),
                "alpha": alpha,
                "r_squared": float(r_squared),
                "rmse": float(rmse),
                "mae": float(mae),
                "x_fitted": x_fit.tolist(),
                "y_fitted": y_fit.tolist(),
                "original_data": {"x": x_data.tolist(), "y": y_data.tolist()}
            }
        
        elif method == "lasso":
            # Lasso回归
            # 生成多项式特征
            poly_features = PolynomialFeatures(degree=degree)
            X_poly = poly_features.fit_transform(x_data.reshape(-1, 1))
            
            # Lasso回归拟合
            lasso = Lasso(alpha=alpha, max_iter=2000)
            lasso.fit(X_poly, y_data)
            
            # 预测和评估
            y_pred = lasso.predict(X_poly)
            r_squared = lasso.score(X_poly, y_data)
            rmse = np.sqrt(mean_squared_error(y_data, y_pred))
            mae = np.mean(np.abs(y_data - y_pred))
            
            # 计算非零系数数量（特征选择效果）
            non_zero_coefs = np.sum(np.abs(lasso.coef_) > 1e-10)
            
            # 生成拟合曲线
            x_fit = np.linspace(min(x_data), max(x_data), 100)
            X_fit_poly = poly_features.transform(x_fit.reshape(-1, 1))
            y_fit = lasso.predict(X_fit_poly)
            
            return {
                "method": f"Lasso回归（{degree}次多项式）",
                "coefficients": lasso.coef_.tolist(),
                "intercept": float(lasso.intercept_),
                "alpha": alpha,
                "r_squared": float(r_squared),
                "rmse": float(rmse),
                "mae": float(mae),
                "non_zero_features": int(non_zero_coefs),
                "x_fitted": x_fit.tolist(),
                "y_fitted": y_fit.tolist(),
                "original_data": {"x": x_data.tolist(), "y": y_data.tolist()}
            }
        
        return "错误：不支持的拟合方法"
        
    except Exception as e:
        return f"错误：曲线拟合失败 - {str(e)}"

@mcp.tool()
def generate_visualization(data: Dict[str, Any], chart_type: str = "matplotlib", title: str = "插值与拟合结果", save_path: Optional[str] = None) -> str:
    """
    生成插值和拟合结果的可视化图表，并直接展示和保存为PNG图像

    Args:
        data: 插值或拟合结果数据
        chart_type: 图表类型 (matplotlib, plotly)
        title: 图表标题
        save_path: 保存图片的路径（可选）

    Returns:
        图片保存路径
    """
    import os
    import datetime
    import sympy as sp
    import matplotlib.pyplot as plt
    import matplotlib.font_manager as fm
    import numpy as np

    try:
        # 处理中文编码
        title = ensure_utf8_encoding(title)
        
        if save_path is None:
            timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
            # 默认保存到模块目录
            module_dir = r"f:\\xzp\\fn-te\\project\\mcp-项智鹏-server\\模块三-插值与拟合模块"
            save_path = os.path.join(module_dir, f"interpolation_visualization_{timestamp}.png")

        # 确保文件路径安全
        save_path = safe_file_path(save_path)
        
        # 确保保存目录存在
        save_dir = os.path.dirname(save_path) if os.path.dirname(save_path) else "."
        os.makedirs(save_dir, exist_ok=True)

        if chart_type == "matplotlib":
            # 确保中文字体设置正确
            setup_chinese_fonts()
            
            # 设置数学公式字体
            try:
                plt.rcParams['mathtext.fontset'] = 'stix'
                plt.rcParams['mathtext.rm'] = 'Times New Roman'
                plt.rcParams['mathtext.it'] = 'Times New Roman:italic'
                plt.rcParams['mathtext.bf'] = 'Times New Roman:bold'
            except Exception as e:
                print(f"数学字体设置失败: {e}")

            plt.figure(figsize=(10, 6), dpi=300)

            # 如果有插值多项式表达式，使用sympy进行数值计算
            if "symbolic_expression" in data and "original_points" in data:
                x = sp.symbols('x')
                polynomial = sp.sympify(data["symbolic_expression"])
                polynomial_func = sp.lambdify(x, polynomial, "numpy")

                x_min = min(data["original_points"]["x"])
                x_max = max(data["original_points"]["x"])
                x_vals = np.linspace(x_min, x_max, 400)

                y_vals = polynomial_func(x_vals)

                # 维度一致性检查
                if len(x_vals) != len(y_vals):
                    min_len = min(len(x_vals), len(y_vals))
                    x_vals = x_vals[:min_len]
                    y_vals = y_vals[:min_len]

                plt.plot(x_vals, y_vals, label=data.get("method", "插值曲线"), c='r', linewidth=2)
                plt.scatter(data["original_points"]["x"], data["original_points"]["y"],
                            c='r', s=60, label='原始数据点', zorder=5)

                if "specific_points" in data:
                    plt.scatter(data["specific_points"]["x"], data["specific_points"]["y"],
                                c='blue', s=80, label='插值计算点', marker='s', zorder=5)

            elif "original_points" in data:
                plt.scatter(data["original_points"]["x"], data["original_points"]["y"],
                            color='red', s=80, label='原始数据点')

                if "x_interpolated" in data and "y_interpolated" in data:
                    x_interp = data["x_interpolated"]
                    y_interp = data["y_interpolated"]

                    # 维度一致性修正
                    if len(x_interp) != len(y_interp):
                        min_len = min(len(x_interp), len(y_interp))
                        x_interp = x_interp[:min_len]
                        y_interp = y_interp[:min_len]
                        print(f"DEBUG: 维度修正 - x长度: {len(data['x_interpolated'])}, y长度: {len(data['y_interpolated'])}, 修正后长度: {min_len}")

                    plt.plot(x_interp, y_interp,
                             'b-', linewidth=2.5, label=data.get("method", "插值曲线"))

                if "target_points" in data:
                    plt.scatter(data["target_points"]["x"], data["target_points"]["y"],
                                color='green', s=100, label='插值计算点', marker='s')

            elif "original_data" in data:
                plt.scatter(data["original_data"]["x"], data["original_data"]["y"],
                            color='red', s=80, label='原始数据点')
                if "x_fitted" in data and "y_fitted" in data:
                    plt.plot(data["x_fitted"], data["y_fitted"],
                             'g-', linewidth=2.5, label=data.get("method", "拟合曲线"))
            



            # 添加插值信息文本（如果有）
            if "interpolation_info" in data:
                info = data["interpolation_info"]
                info_text = f"原始点数: {info.get('original_points_count', '?')}\n插值点数: {info.get('interpolated_points_count', '?')}"
                plt.text(0.02, 0.98, info_text, transform=plt.gca().transAxes,
                         verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8))

            # 自动设置坐标轴范围，添加5%边距
            all_x = []
            all_y = []
            if "original_points" in data:
                all_x.extend(data["original_points"]["x"])
                all_y.extend(data["original_points"]["y"])
            if "x_interpolated" in data and "y_interpolated" in data:
                all_x.extend(data["x_interpolated"])
                all_y.extend(data["y_interpolated"])
            if all_x and all_y:
                x_min, x_max = min(all_x), max(all_x)
                y_min, y_max = min(all_y), max(all_y)
                x_margin = (x_max - x_min) * 0.05 if x_max > x_min else 1
                y_margin = (y_max - y_min) * 0.05 if y_max > y_min else 1
                plt.xlim(x_min - x_margin, x_max + x_margin)
                plt.ylim(y_min - y_margin, y_max + y_margin)

            # 处理标题中的R²符号，使用LaTeX渲染
            if 'R²' in title:
                title = title.replace('R²', r'$R^2$')
            elif 'R^2' in title:
                title = title.replace('R^2', r'$R^2$')
            
            plt.title(title, fontsize=16)
            plt.legend(fontsize=12)
            plt.grid(True, alpha=0.3)
            plt.tight_layout()

            # 保存图片，确保路径编码正确
            try:
                plt.savefig(save_path, format='png', dpi=300, bbox_inches='tight', 
                           facecolor='white', edgecolor='none')
                print(f"图片已成功保存到: {save_path}")
            except Exception as save_error:
                print(f"保存图片时出错: {save_error}")
                # 尝试使用备用路径
                backup_path = "backup_plot.png"
                plt.savefig(backup_path, format='png', dpi=300, bbox_inches='tight',
                           facecolor='white', edgecolor='none')
                save_path = backup_path
                print(f"已保存到备用路径: {backup_path}")
            finally:
                plt.close()

        elif chart_type == "plotly":
            import plotly.graph_objects as go
            fig = go.Figure()

            if "original_points" in data:
                fig.add_trace(go.Scatter(
                    x=data["original_points"]["x"], y=data["original_points"]["y"],
                    mode='markers', name='原始数据点', marker=dict(size=8, color='red')))
                if "x_interpolated" in data and "y_interpolated" in data:
                    x_interp = data["x_interpolated"]
                    y_interp = data["y_interpolated"]

                    # 维度一致性修正
                    if len(x_interp) != len(y_interp):
                        min_len = min(len(x_interp), len(y_interp))
                        x_interp = x_interp[:min_len]
                        y_interp = y_interp[:min_len]
                        print(f"DEBUG: Plotly维度修正 - x长度: {len(data['x_interpolated'])}, y长度: {len(data['y_interpolated'])}, 修正后长度: {min_len}")

                    fig.add_trace(go.Scatter(
                        x=x_interp, y=y_interp,
                        mode='lines', name=data.get("method", "插值曲线"),
                        line=dict(color='blue', width=2)))

            elif "original_data" in data:
                fig.add_trace(go.Scatter(
                    x=data["original_data"]["x"], y=data["original_data"]["y"],
                    mode='markers', name='原始数据点', marker=dict(size=8, color='red')))
                if "x_fitted" in data and "y_fitted" in data:
                    fig.add_trace(go.Scatter(
                        x=data["x_fitted"], y=data["y_fitted"],
                        mode='lines', name=data.get("method", "拟合曲线"),
                        line=dict(color='green', width=2)))

            # 设置布局，确保中文显示正确
            fig.update_layout(
                title=dict(text=title, font=dict(size=16)),
                xaxis_title='X', 
                yaxis_title='Y',
                font=dict(family="Microsoft YaHei, SimHei, Arial", size=12)
            )

            # 保存为PNG图像
            try:
                fig.write_image(save_path, format="png", width=1200, height=800, scale=2)
                print(f"Plotly图片已成功保存到: {save_path}")
            except Exception as e:
                print(f"Plotly图像保存失败：{e}")
                # 尝试使用备用路径
                backup_path = "backup_plotly.png"
                try:
                    fig.write_image(backup_path, format="png", width=1200, height=800, scale=2)
                    save_path = backup_path
                    print(f"已保存到备用路径: {backup_path}")
                except Exception as backup_error:
                    raise RuntimeError(f"Plotly图像保存完全失败：{backup_error}，请确认已安装 kaleido（pip install kaleido）")

        else:
            raise ValueError("不支持的图表类型: 请选择 'matplotlib' 或 'plotly'")

        # 确保返回的路径使用正确编码
        safe_path = ensure_utf8_encoding(save_path)
        return f"图像已保存到: {safe_path}"

    except Exception as e:
        error_msg = ensure_utf8_encoding(str(e))
        return f"错误：可视化生成失败 - {error_msg}"



@mcp.tool()
def evaluate_polynomial(polynomial: str, x_value: List[float]) -> Union[Dict[str, Any], str]:
    """
    计算多项式在给定x值处的函数值
    
    Args:
        polynomial: 多项式表达式字符串，如 "x**2 + 2*x + 1"
        x_value: x值列表
    
    Returns:
        计算结果
    """
    try:
        import sympy as sp
        
        print(f"DEBUG: evaluate_polynomial - 输入多项式: {polynomial}")
        print(f"DEBUG: evaluate_polynomial - 输入x值: {x_value}")
        
        # 解析多项式表达式
        x = sp.Symbol('x')
        poly_expr = sp.sympify(polynomial)
        
        print(f"DEBUG: evaluate_polynomial - 解析后的表达式: {poly_expr}")
        
        # 计算每个x值对应的函数值
        results = []
        for x_val in x_value:
            value = float(poly_expr.subs(x, x_val).evalf())
            results.append(value)
            print(f"DEBUG: evaluate_polynomial - x={x_val}, y={value}")
        
        result = {
            "polynomial": polynomial,
            "x_values": x_value,
            "results": results,
            "method": "多项式计算"
        }
        
        print(f"DEBUG: evaluate_polynomial - 返回结果: {result}")
        return result
        
    except Exception as e:
        error_msg = f"错误：多项式计算失败 - {str(e)}"
        print(f"DEBUG: evaluate_polynomial - 错误: {error_msg}")
        return error_msg

@mcp.tool()
def evaluate_fitting_accuracy(x_data: List[float], y_data: List[float], y_fitted: List[float]) -> Union[Dict[str, Any], str]:
    """
    评估拟合精度
    
    Args:
        x_data: 原始x数据
        y_data: 原始y数据
        y_fitted: 拟合的y数据
    
    Returns:
        详细的拟合精度评估结果
    """
    try:
        x_data = np.array(x_data)
        y_data = np.array(y_data)
        y_fitted = np.array(y_fitted)
        
        if len(y_data) != len(y_fitted):
            return "错误：原始数据和拟合数据长度不匹配"
        
        # 计算各种评估指标
        r_squared = r2_score(y_data, y_fitted)
        rmse = np.sqrt(mean_squared_error(y_data, y_fitted))
        mae = np.mean(np.abs(y_data - y_fitted))
        mape = np.mean(np.abs((y_data - y_fitted) / y_data)) * 100  # 平均绝对百分比误差
        
        # 残差分析
        residuals = y_data - y_fitted
        residual_std = np.std(residuals)
        residual_mean = np.mean(residuals)
        
        # 计算相关系数
        correlation = np.corrcoef(y_data, y_fitted)[0, 1]
        
        # 计算调整R²（需要知道参数个数，这里假设为2）
        n = len(y_data)
        p = 2  # 假设参数个数
        adjusted_r2 = 1 - (1 - r_squared) * (n - 1) / (n - p - 1)
        
        return {
            "r_squared": float(r_squared),
            "adjusted_r_squared": float(adjusted_r2),
            "rmse": float(rmse),
            "mae": float(mae),
            "mape": float(mape),
            "correlation": float(correlation),
            "residual_analysis": {
                "mean": float(residual_mean),
                "std": float(residual_std),
                "min": float(np.min(residuals)),
                "max": float(np.max(residuals))
            },
            "data_points": int(n),
            "fitting_quality": "优秀" if r_squared > 0.9 else "良好" if r_squared > 0.7 else "一般" if r_squared > 0.5 else "较差"
        }
        
    except Exception as e:
        return f"错误：拟合精度评估失败 - {str(e)}"

# 启动服务器
if __name__ == "__main__":
    print("启动插值与拟合MCP服务器...")
    mcp.run()